/*
 * Copyright (c) 2005, 2014 vacoor
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package org.ponly.uno4j.core;

import com.sun.star.beans.PropertyValue;
import com.sun.star.frame.XComponentLoader;
import com.sun.star.frame.XStorable;
import com.sun.star.lang.IllegalArgumentException;
import com.sun.star.lang.XComponent;
import com.sun.star.lib.uno.adapter.OutputStreamToXOutputStreamAdapter;
import org.ponly.uno4j.io.SeekableInputStream;
import org.ponly.uno4j.io.SeekableInputStreamToXSeekableInputStreamAdapter;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import static org.ponly.uno4j.util.UnoUtils.*;

/**
 * UNO 读写支持
 *
 * @author vacoor
 * @see <a href="http://www.openoffice.org/api/docs/common/ref/com/sun/star/document/MediaDescriptor.html">OOo MediaDescriptor</a>
 */
public abstract class UnoSupport {

    /**
     * 使用给定的组件器加载文件
     *
     * @param xCompLoader    组件加载器
     * @param source         要加载的文件
     * @param propertyValues 加载选项
     * @return 加载完的完成对象
     * @throws IOException
     * @throws IllegalArgumentException
     * @throws IOException
     * @throws IllegalArgumentException
     * @throws com.sun.star.io.IOException
     */
    protected XComponent load(XComponentLoader xCompLoader, File source, PropertyValue[] propertyValues) throws IOException, IllegalArgumentException, IOException, IllegalArgumentException, com.sun.star.io.IOException {
        if (!source.exists() || !source.canRead()) {
            throw new IllegalArgumentException("不能读取文件：" + source);
        }
        // return load(xCompLoader, new SeekableFileInputStream(source), propertyValues);
        return load(xCompLoader, toUrl(source), propertyValues);
    }

    /**
     * 使用给定的组件加载器加载输入流
     *
     * @param xCompLoader    组件加载器
     * @param source         要加载的输入流
     * @param propertyValues 加载选项
     * @deprecated 过时发现效率太低, 比 file:///home/vacoor/user.xls 效率低太多
     */
    @Deprecated
    protected XComponent load(XComponentLoader xCompLoader, SeekableInputStream source, PropertyValue[] propertyValues) throws com.sun.star.io.IOException, IllegalArgumentException {
        return load(
                xCompLoader,
                "private:stream",
                merge(propertyValues, of(
                        "InputStream",
                        new SeekableInputStreamToXSeekableInputStreamAdapter(source)
                ))
        );
    }

    /**
     * 使用给定的组件器加载文件
     *
     * @param xCompLoader    组件加载器
     * @param url            要加载的url
     * @param propertyValues 加载选项
     * @deprecated 不建议使用, 注意当 URL 对应文件不存在时不会报错, 会一直阻塞, 以后查找原因
     */
    @Deprecated
    protected XComponent load(XComponentLoader xCompLoader, String url, PropertyValue[] propertyValues) throws com.sun.star.io.IOException, IllegalArgumentException {
        return xCompLoader.loadComponentFromURL(url, "_blank", 0, propertyValues);
    }

    // --------------- store

    protected void store(XStorable xStorable, File out, PropertyValue[] propertyValues) throws IOException {
        store(xStorable, new FileOutputStream(out), propertyValues);
    }

    /**
     * 将给定的 XStorable 使用给定的存储选项存储到给定的输出流
     *
     * @param xStorable      要存储的对象
     * @param out            输出流
     * @param propertyValues 存储选项
     */
    protected void store(XStorable xStorable, OutputStream out, PropertyValue[] propertyValues) throws IOException {
        store(
                xStorable,
                "private:stream",
                merge(propertyValues, of(
                        "OutputStream",
                        new OutputStreamToXOutputStreamAdapter(out)
                ))
        );
    }

    /**
     * 将给定 xStorable 存储到给定的 url
     * <p>
     * 注意: 对于文件系统 URL 使用 file:/// 开头, 而 java 是 file:/ 开头, 需要自行转换(eg: file:///opt --> file:///opt)
     * URL 对应路径如果不存在会自动创建所需路径
     * <p>
     * <strong>建议使用以下两个方法</strong>:
     * {@link #store(com.sun.star.frame.XStorable, java.io.OutputStream, com.sun.star.beans.PropertyValue[])}
     * {@link #store(com.sun.star.frame.XStorable, java.io.File, com.sun.star.beans.PropertyValue[])}
     *
     * @param xStorable      存储对象
     * @param url            存储的目的 URL
     * @param propertyValues 存储选项
     */
    protected void store(XStorable xStorable, String url, PropertyValue[] propertyValues) throws IOException {
        try {
            xStorable.storeToURL(url, propertyValues);
        } catch (com.sun.star.io.IOException e) {
            throw new IOException(e);
        }
    }
}
